package com.jxpanda.spring.module.auth.endpoint;

import com.jxpanda.spring.module.auth.core.token.OAuth2TokenPayload;
import com.jxpanda.spring.module.auth.endpoint.handler.ReactiveAuthenticationSuccessHandler;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.util.Assert;

import java.time.Duration;
import java.time.Instant;
import java.util.Map;


/**
 * 这个对象没有通过@JsonProperty注解控制属性名的序列化
 * 如果要强制返回某一个命名风格，可以通过{@link  ReactiveAuthenticationSuccessHandler}来处理
 */
@Data
@Schema(description = "OAuth2 响应对象")
public class OAuth2Response {

    @Schema(description = "访问令牌，用于访问受保护资源", example = "eyJhbGciOiJIUzI1NiIsInR5...")
    private String accessToken;

    @Schema(description = "令牌类型，例如 Bearer", example = "Bearer")
    private String tokenType;

    @Schema(description = "令牌的有效期，单位为秒", example = "3600")
    private Long expiresIn;

    @Schema(description = "刷新令牌，用于获取新的访问令牌", example = "8xLOxBtZp8")
    private String refreshToken;

    // TODO: 用户信息暂时注释掉，因为有泄漏密码的风险，之后在考虑要如何处理
//    @Schema(description = "用户信息，可能包含用户的详细信息", example = "{ \"id\": \"12345\", \"name\": \"John Doe\" }")
//    private Object userInfo;

    @Schema(description = "其他需要返回的参数")
    private Map<String, Object> additionalParameters;

    public static OAuth2Response of(OAuth2TokenPayload oAuth2TokenPayload) {
        OAuth2Response response = new OAuth2Response();
        OAuth2AccessToken accessToken = oAuth2TokenPayload.getAccessToken();
        response.setAccessToken(accessToken.getTokenValue());
        response.setTokenType(accessToken.getTokenType().getValue());
        Instant expiresAt = accessToken.getExpiresAt();
        Instant issuedAt = accessToken.getIssuedAt();
        Assert.notNull(issuedAt, "issuedAt must not be null");
        Assert.notNull(expiresAt, "expiresAt must not be null");
        response.setExpiresIn(Duration.between(issuedAt, expiresAt).getSeconds());
        response.setRefreshToken(oAuth2TokenPayload.getRefreshToken().getTokenValue());
//        response.setUserInfo(oAuth2TokenPayload.getUserDetails());
        return response;
    }

}

